package apartado2;

import java.util.Iterator;
import java.util.List;
import java.util.Properties;

import aima.core.agent.Action;
import aima.core.search.framework.GraphSearch;
import aima.core.search.framework.Problem;
import aima.core.search.framework.Search;
import aima.core.search.framework.SearchAgent;
import aima.core.search.framework.TreeSearch;
import aima.core.search.informed.AStarSearch;
import aima.core.search.uninformed.BreadthFirstSearch;
import aima.core.search.uninformed.IterativeDeepeningSearch;

public class OchoPuzzleDemo {
	
	static OchoPuzzleTablero medium = new OchoPuzzleTablero(new int[] { 1, 4, 2, 7, 5, 8, 3, 0, 6});
	
	public static void main(String[] args) {
		ochoPuzzleAnchuraDemo();
		ochoPuzzleProfundidadDemo();
		ochoPuzzleAEstrella_Arbol_Descolocadas();
		ochoPuzzleAEstrella_Arbol_Manhattan();
		ochoPuzzleAEstrella_Grafo_Descolocadas();
		ochoPuzzleAEstrella_Grafo_Manhattan();
	}

	private static void ochoPuzzleAnchuraDemo() {
		System.out.println("\nOchoPuzzleDemo Anchura Demo -->");
		try {
			Problem problem = new Problem(
					medium, 
					OchoPuzzleFunctionFactory.getActionsFunction(), 
					OchoPuzzleFunctionFactory.getResultFunction(), 
					new OchoPuzzleGoalTest()
					);
			Search search = new BreadthFirstSearch(new GraphSearch());
			SearchAgent agent = new SearchAgent(problem, search);
			printActions(agent.getActions());
			printInstrumentation(agent.getInstrumentation());
		} catch (Exception e) {
			e.printStackTrace();
		}

	}
	
	private static void ochoPuzzleProfundidadDemo() {
		System.out.println("\nOchoPuzzleDemo Profundidad Demo -->");
		try {
			Problem problem = new Problem(
					medium, 
					OchoPuzzleFunctionFactory.getActionsFunction(), 
					OchoPuzzleFunctionFactory.getResultFunction(), 
					new OchoPuzzleGoalTest()
					);
			Search search = new IterativeDeepeningSearch();
			SearchAgent agent = new SearchAgent(problem, search);
			printActions(agent.getActions());
			printInstrumentation(agent.getInstrumentation());
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	private static void ochoPuzzleAEstrella_Arbol_Descolocadas() {
		System.out.println("\nOchoPuzzleDemo A* en Arbol con Descolocadas Demo -->");
		try {
			Problem problem = new Problem(
					medium, 
					OchoPuzzleFunctionFactory.getActionsFunction(), 
					OchoPuzzleFunctionFactory.getResultFunction(), 
					new OchoPuzzleGoalTest()
					);
			Search search = new AStarSearch(
					new TreeSearch(),
					new FuncionHeuristicaCasillasDescolocadas());
			SearchAgent agent = new SearchAgent(problem, search);
			printActions(agent.getActions());
			printInstrumentation(agent.getInstrumentation());
		} catch (Exception e) {
			e.printStackTrace();
		}

	}
	
	private static void ochoPuzzleAEstrella_Arbol_Manhattan() {
		System.out.println("\nOchoPuzzleDemo A* en Arbol con Manhattan Demo -->");
		try {
			Problem problem = new Problem(
					medium, 
					OchoPuzzleFunctionFactory.getActionsFunction(), 
					OchoPuzzleFunctionFactory.getResultFunction(), 
					new OchoPuzzleGoalTest()
					);
			Search search = new AStarSearch(
					new TreeSearch(),
					new FuncionHeuristicaManhattan()
					);
			SearchAgent agent = new SearchAgent(problem, search);
			printActions(agent.getActions());
			printInstrumentation(agent.getInstrumentation());
		} catch (Exception e) {
			e.printStackTrace();
		}

	}
	
	private static void ochoPuzzleAEstrella_Grafo_Descolocadas() {
		System.out.println("\nOchoPuzzleDemo A* en Grafo con Descolocadas Demo -->");
		try {
			Problem problem = new Problem(
					medium, 
					OchoPuzzleFunctionFactory.getActionsFunction(), 
					OchoPuzzleFunctionFactory.getResultFunction(), 
					new OchoPuzzleGoalTest()
					);
			Search search = new AStarSearch(
					new GraphSearch(),
					new FuncionHeuristicaCasillasDescolocadas()
					);
			SearchAgent agent = new SearchAgent(problem, search);
			printActions(agent.getActions());
			printInstrumentation(agent.getInstrumentation());
		} catch (Exception e) {
			e.printStackTrace();
		}

	}
	
	private static void ochoPuzzleAEstrella_Grafo_Manhattan() {
		System.out.println("\nOchoPuzzleDemo A* en Grafo con Manhattan Demo -->");
		try {
			Problem problem = new Problem(
					medium, 
					OchoPuzzleFunctionFactory.getActionsFunction(), 
					OchoPuzzleFunctionFactory.getResultFunction(), 
					new OchoPuzzleGoalTest()
					);
			Search search = new AStarSearch(
					new GraphSearch(),
					new FuncionHeuristicaManhattan()
					);
			SearchAgent agent = new SearchAgent(problem, search);
			printActions(agent.getActions());
			printInstrumentation(agent.getInstrumentation());
		} catch (Exception e) {
			e.printStackTrace();
		}

	}
	
	private static void printInstrumentation(Properties properties) {
		Iterator<Object> keys = properties.keySet().iterator();
		while (keys.hasNext()) {
			String key = (String) keys.next();
			String property = properties.getProperty(key);
			System.out.println(key + " : " + property);
		}

	}

	private static void printActions(List<Action> actions) {
		for (int i = 0; i < actions.size(); i++) {
			String action = actions.get(i).toString();
			System.out.println(action);
		}
	}
}
